import Cesium from '../Ces/Cesium'
import WeUniform from './WeUniform'

class WeDisplayEffectNumber {
  batchTable: any
  texture: any
  private _weUniform: WeUniform
  constructor(frameState) {
    const attributes = [
      {
        functionName: 'getTextBoundingbox',
        componentDatatype: Cesium.ComponentDatatype.FLOAT,
        componentsPerAttribute: 4,
      },
    ]
    this.batchTable = new Cesium.BatchTable(frameState.context, attributes, 64)
    const floatUniform = {
      repeatFactor: 1.0,
      marginW: 0.1,
      marginH: 0.3,
      singlePrecision: 1.0,
    }
    this.texture = new Cesium.Texture({
      context: frameState.context,
      source: this.createCanvas(),
      flipY: false,
    })

    this._weUniform = new WeUniform({ floatUniform, name: 'WeDisplayEffectIcon' });
    this.batchTable.update(frameState)
  }

  set repeatFactor(value) {
    this._weUniform.Properties.repeatFactor = value
  }

  get repeatFactor() {
    return this._weUniform.Properties.repeatFactor
  }

  createCanvas() {
    const text = '0123456789.℃m/s'
    const font = '128px msyh'

    const images: any = []

    const atalsCanvas = document.createElement('canvas')
    atalsCanvas.width = 1024 * 2
    atalsCanvas.height = 128
    const atalsContext = atalsCanvas.getContext('2d')
    let offsetX = 0
    for (let i = 0; i < text.length; i++) {
      const canvas = Cesium.writeTextToCanvas(text[i], {
        font,
        stroke: true,
        strokeWidth: 4,
        padding: 1,
      })
      images.push(canvas)
      atalsContext?.drawImage(images[i], offsetX, 0)
      this.batchTable.setBatchedAttribute(
        i,
        0,
        new Cesium.Cartesian4(
          offsetX / atalsCanvas.width,
          canvas.width / atalsCanvas.width,
          canvas.height / atalsCanvas.height,
          4,
        ),
      )
      offsetX += canvas.width
    }

    return atalsCanvas
  }

  setupUniform(uniforms) {
    this._weUniform.setupUniform(uniforms)
    uniforms.u_IconNumberTexture = this.texture
    uniforms.u_IconNumberBatch = this.batchTable._texture
    uniforms.batchTextureStep2 = this.batchTable._textureStep
  }

  getSource(): string {
    // const batchSource = this.batchTable.getVertexShaderCallback()('')
    const batchSource = `
    vec2 computeSt2(float batchId)
    {
        float stepX = batchTextureStep2.x;
        float centerX = batchTextureStep2.y;
        float numberOfAttributes = float(1);
        return vec2(centerX + (batchId * numberOfAttributes * stepX), 0.5);
    }

    vec4 getTextBoundingbox(float batchId)
    {
        vec2 st = computeSt2(batchId);
        st.x += batchTextureStep2.x * float(0);
        vec4 textureValue = texture(u_IconNumberBatch, st);
        vec4 value = textureValue;
        return value;
    }
    `
    return `
        ${this._weUniform.getSource(false)}
        ${batchSource}
        precision highp float;
    #ifdef IS_SAMPLER3D
        vec4 WeIcon(vec3 uv)
#else
        vec4 WeIcon(vec2 uv)
#endif
        {
            vec4 color = vec4(0.0,0.0,0.0,0.0);
            bool shouldFlipY = Weget_shouldFlipY() > 0.0;
            if(!shouldFlipY){
                uv.y = 1.0 - uv.y;
            }

            float repeatFactor = Weget_repeatFactor();
            vec2 repeat = floor(u_textureResolution / repeatFactor);
            vec2 st = uv.xy;
            vec2 iconUV = fract(st * repeat);
            vec2 iconID = floor(st * repeat);
            iconID /= repeat;

            if(!shouldFlipY){
              iconID.y = 1.0 - iconID.y;
            }

            st = iconUV;

            float value = WeDecodeValue(vec2(iconID));

            float v0 = floor(mod(value,100.0) / 10.0);
            float v1 = floor(mod(value,10.0));
            float v2 = floor(mod(value * 10.0,10.0));
            float v3 = floor(mod(value * 100.0,10.0));

            vec4 id0 = getTextBoundingbox(v0);
            vec4 id1 = getTextBoundingbox(v1);
            vec4 id2 = getTextBoundingbox(10.0);
            vec4 id3 = getTextBoundingbox(v2);
            vec4 id4 = getTextBoundingbox(v3);

            bool singlePrecision = Weget_singlePrecision() > 0.0;
            float n = singlePrecision ? 7.0 : 9.0;

            float offset0 = 2.0 / n;
            float offset1 = 2.0 / n;
            float offset2 = 1.0 / n;
            float offset3 = 2.0 / n;
            float offset4 = 2.0 / n;

            float marginW = Weget_marginW();
            float marginH = Weget_marginH();
            if(st.y > marginH && st.y < (1.0 - marginH)
            && st.x > marginW && st.x < (1.0 - marginW)){
              st.y -= marginH;
              st.y /= (1.0 - marginH * 2.0);
              st.x -= marginW;
              st.x /= (1.0 - marginW * 2.0);

              if(st.x < offset0) {
                st.x /= offset0;
                st.x = id0.x + st.x * id0.y;
                st.y = st.y * id0.z;
                if(v0 == 0.0) st *= 0.0;
              }
              else if(st.x < offset0 + offset1) {
                st.x -= offset0;
                st.x /= offset1;
                st.x = id1.x + st.x * id1.y;
                st.y = st.y * id1.z;
              }
              else if(st.x < offset0 + offset1 + offset2) {
                st.y = 1.0 - st.y;
                st.y /= 0.2;
                st.x -= offset0 + offset1;
                st.x /= offset2;
                st.x = id2.x + st.x * id2.y;
                st.y = st.y * id2.z;
              } else if(st.x < offset0 + offset1 + offset2 + offset3) {
                st.x -= offset0 + offset1 + offset2;
                st.x /= offset3;
                st.x = id3.x + st.x * id3.y;
                st.y = st.y * id3.z;
              }
              else{
                st.x -= offset0 + offset1 + offset2 + offset3;
                st.x /= offset4;
                st.x = id4.x + st.x * id4.y;
                st.y = st.y * id4.z;
                if(v3 == 0.0) st *= 0.0;
              }

              color = texture(u_IconNumberTexture, st);
              // color = vec4(st,0.0,1.0);
            }

            // vec4 uvColor = vec4(iconUV,0.0,1.0);
            // color = mix(uvColor,color,0.5);

            return color;
          }
    `
  }

  isDestroyed() {
    return false
  }
  destroy() {
    this.texture = this.texture?.destroy()
    this.batchTable = this.batchTable?.destroy()
    return Cesium.destroyObject(this)
  }
}

export default WeDisplayEffectNumber
